using System;
using System.Collections.Generic;
using System.Linq;

namespace AutoTest.Core.Utils
{
    public static class TypeExtension
    {
        public static bool ImplementsInterface<TInterface>(this Type typeThatMayImplementInterface)
        {
            return typeThatMayImplementInterface.ImplementsInterface(typeof (TInterface));
        }

        public static bool ImplementsInterface(this Type typeThatMayImplementInterface, Type interfaceType)
        {
            return typeThatMayImplementInterface.IsClass &&
                   (interfaceType.IsAssignableFrom(typeThatMayImplementInterface) ||
                    typeThatMayImplementInterface.ImplementsClosedGenericInterface(interfaceType));
        }

        private static bool ImplementsClosedGenericInterface(this Type typeThatMayImplementInterface,
                                                             Type openGenericInterface)
        {
            return FindGenericInterfaces(typeThatMayImplementInterface, new[] {openGenericInterface}).Count() > 0;
        }

        public static Type FindGenericInterface(this Type typeThatMayImplementInterface, Type openGenericInterface)
        {
            return typeThatMayImplementInterface.GetInterfaces().ToList().FirstOrDefault(
                i => i.IsGenericType && i.GetGenericTypeDefinition() == openGenericInterface);
        }

        public static IEnumerable<Type> FindGenericInterfaces(this Type typeThatMayImplementInterface, IEnumerable<Type> openGenericInterfaces)
        {
            return typeThatMayImplementInterface.GetInterfaces().ToList().Where(
                i => i.IsGenericType && openGenericInterfaces.Contains(i.GetGenericTypeDefinition()));
        }

        public static Type GetGenericArgumentFor(this Type typeThatImplementsGenericInterface, Type openGenericInterface)
        {
            return typeThatImplementsGenericInterface.GetInterfaces().ToList()
                .First(i => i.IsGenericType && i.GetGenericTypeDefinition() == openGenericInterface)
                .GetGenericArguments()[0];
        }
    }
}